package com.shortvedio.media.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.persistent.FileRecorder;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import com.qiniu.util.StringUtils;
import com.qiniu.util.UrlSafeBase64;
import com.shortvedio.base.mapper.SUserInfoMapper;
import com.shortvedio.base.mapper.TaskVedioMapper;
import com.shortvedio.base.model.po.SUserInfo;
import com.shortvedio.media.model.dto.VideoKeyDto;
import com.shortvedio.media.service.MediaService;
import com.shortvedio.base.exception.ShortVedioPlusException;
import com.shortvedio.base.model.Result;
import com.shortvedio.base.model.po.TaskVedio;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Paths;
import java.time.LocalDateTime;

@Service
@Slf4j
public class MediaServiceImpl implements MediaService {


    @Value("${qiniu.bucket}")
    private String bucket;

    @Autowired
    private Configuration configuration;

    @Autowired
    private Auth auth;

    @Autowired
    private TaskVedioMapper taskVedioMapper;

    @Autowired
    private SUserInfoMapper sUserInfoMapper;

    @Value("${qiniu.http}")
    private String http;

    @Override
    public String uploadPicture(String localPath) {
        UploadManager uploadManager = new UploadManager(configuration);
        File file = new File(localPath);
        String upToken = auth.uploadToken(bucket,file.getName());
        log.info("uptoken:{}",upToken);
        Response response = null;
        DefaultPutRet putRet = null;
        try {
            response = uploadManager.put(file,file.getName(),upToken);
            putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
        } catch (QiniuException e) {
            ShortVedioPlusException.cast("上传失败请重试");
        }
        log.info("putRet.key:{}",putRet.key);
        String fileName = putRet.key;
        return fileName;
    }

    //获得视频的md5值
    private String getFileMd5(File file) {//得到视频文件的md5值
        try (FileInputStream fileInputStream = new FileInputStream(file)) {
            String fileMd5 = DigestUtils.md5Hex(fileInputStream);
            return fileMd5;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public Result uploadVedio(String localPath) {
        //断点续传
        configuration.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
        configuration.resumableUploadMaxConcurrentTaskCount = 2;
        //获取文件名称
        File file = new File(localPath);
        String localName = file.getName();
        String name = getFileMd5(file);

        String lastName = localName.substring(localName.lastIndexOf("."));
        String fileName = name + lastName;
        //对文件进行处理  统一文件格式 获取文件截图
        String saveMp4Entry = String.format("%s:"+name+".mp4", bucket);
        String saveJpgEntry = String.format("%s:"+name+".png", bucket);
        //使用libx264进行编码 同时获取视频截图
        String avthumbMp4Fop = String.format("avthumb/mp4/vcodec/libx264|saveas/%s", UrlSafeBase64.encodeToString(saveMp4Entry));
        String vframeJpgFop = String.format("vframe/jpg/offset/1|saveas/%s", UrlSafeBase64.encodeToString(saveJpgEntry));

        StringMap putPolicy = new StringMap();
        String persistentOpfs = StringUtils.join(new String[]{
                avthumbMp4Fop, vframeJpgFop
        }, ";");
        //参数添加
        putPolicy.put("persistentOps", persistentOpfs);
        putPolicy.put("persistentNotifyUrl", http+"/media/add_tesk_callback");
        //数据处理队列名称
        putPolicy.put("persistentPipeline", "hehewang");
        long expireSeconds = 3600;
        String upToken = auth.uploadToken(bucket, fileName, expireSeconds, putPolicy);
        String localTempDir = Paths.get(System.getenv("java.io.tmpdir"), bucket).toString();
        log.info("视频上传测试");
        log.info("time:{}", LocalDateTime.now());
        try {
            //设置断点续传文件进度保存目录
            FileRecorder fileRecorder = new FileRecorder(localTempDir);
            UploadManager uploadManager = new UploadManager(configuration, fileRecorder);
            Response response = uploadManager.put(localPath, fileName, upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            String key = putRet.key;
            VideoKeyDto videoKeyDto = new VideoKeyDto();
            videoKeyDto.setVedioId(name);
            videoKeyDto.setFilePath(key);
            return Result.success(videoKeyDto);
        } catch (IOException ex) {
            ShortVedioPlusException.cast("上传失败，请重试");
        }
        return null;
    }

    @Override
    public void AddTeskVedio(String inputKey) {
        //添加任务信息
        TaskVedio taskVedio = new TaskVedio();
        taskVedio.setInputkey(inputKey);
        taskVedio.setStatus(0);
        taskVedio.setCreatTime(LocalDateTime.now());
        int insert = taskVedioMapper.insert(taskVedio);
        if (insert<=0){
            ShortVedioPlusException.cast("添加任务失败");
        }
    }

    @Override
    public void deleteFile(String fileName) {
        //删除文件
        BucketManager bucketManager = new BucketManager(auth, configuration);
        try {

            bucketManager.delete(bucket, fileName);
        } catch (QiniuException ex) {
            //如果遇到异常
            return;
//            ShortVedioPlusException.cast("删除文件失败");
        }
    }

    @Override
    public void updateUserHeadSrc(String headSrc, Long userId) {
        LambdaQueryWrapper<SUserInfo> sUserInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sUserInfoLambdaQueryWrapper.eq(SUserInfo::getUserId,userId);
        SUserInfo sUserInfo = sUserInfoMapper.selectOne(sUserInfoLambdaQueryWrapper);
        if (sUserInfo==null){
            return;
        }
        sUserInfo.setHeadSrc(headSrc);
        sUserInfoMapper.updateById(sUserInfo);
    }

}
